package cn.edu.nju.ws.sview.views;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;

import cn.edu.nju.ws.sview.database.DBConnectionFactory;
import cn.edu.nju.ws.sview.rdf.ResourceFactory;
import cn.edu.nju.ws.sview.rdf.URIResource;
import cn.edu.nju.ws.sview.reasoning.Predicate;
import cn.edu.nju.ws.sview.reasoning.ProductionMemory;
import cn.edu.nju.ws.sview.reasoning.Rule;
import cn.edu.nju.ws.sview.views.data.EntityManagement;

/**
 * user defined datamembers, not include origin rdf properties 
 * 
 * 删除一个datamember 需要 1. 将dm_from表中将那些依赖于该datamember的记录删除 2. 将dm_from
 * 表中该datamember依赖的记录删除 3. 将view_dm中该datamember相关的记录删除 4.
 * 将data_member表中该datamember删除
 * 
 * 新建一个datamember需要 1.在dm_from表中记录该datamember依赖的记录 2. 在datamember中插入该datamember
 * 
 * @author ssgong
 */
public class CustomDataMember extends DataMember {
	private String name;
	private int valueType = -1;
	private int makeMethod = -1;
	private ArrayList<Base> bases = null;
	private int classID;
	private int id;
	private int arity;
	private boolean functional;
	private String group;
	private boolean isInner;
	//see whether it is made from copy
	private boolean isCopy ;

	public CustomDataMember(String name, String group, int valueType,
			int makeMethod, ArrayList<Base> from, boolean isInner, int classID,boolean isCopy) {
		this.name = name;
		this.group = group;
		this.makeMethod = makeMethod;
		this.classID = classID;
		this.valueType = valueType;
		this.isInner = isInner;
		this.isCopy = isCopy;
		
		int groupID = Group.getGroupIdByName(this.group);
		ArrayList<Base> bases = new ArrayList<Base>();
		HashSet<Base> visited = new HashSet<Base>();
		for (Base base : from) {
			if (!visited.contains(base)) {
				visited.add(base);
				int type = base.getDMType();
				int id = base.getID();
				boolean inverse = base.isInverse();
				if (type == DataMember.URI_DATAMEMBER) {
					bases.add(base);
				} else {
					boolean hasAuthor = CustomDataMember.hasAuthor(groupID, id);
					if (hasAuthor) {
						bases.add(base);
					} else {
						CustomDataMember cdm = CustomDataMember
								.getCustomDataMemberById(id).deepCopy();
						int copyID = cdm.getID();
						CustomDataMember.setTMP(copyID, false);
						Base newbase = new Base(type, copyID, inverse);
						bases.add(newbase);
					}
				}
			}
		}
		this.bases = bases;
	}

	public CustomDataMember(String name, String group, int valueType,
			int makeMethod, boolean isInner, int classID,boolean isCopy) {
		this.name = name;
		this.group = group;
		this.makeMethod = makeMethod;
		this.classID = classID;
		this.valueType = valueType;
		this.isInner = isInner;
		this.isCopy = isCopy;
	}
	
	public static boolean hasAuthor(int groupID,int dmid){
		boolean result = false;
		try {
			Connection conn = DBConnectionFactory.getConnection();
			Statement stmt = conn.createStatement();
			ResultSet rs = stmt
					.executeQuery(String.format(
							"select null from data_member "
									+ "where id=%d and group_id=%d and isCopy=0", dmid,groupID));
			if (rs.next()) {
				result = true;
			}
			rs.close();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return result;
	}
	
	/**
	 * light copy and return the top datamember
	 * 每次拷贝时均在原来的名字后面生成"(version)"
	 * @return
	 */
	private  CustomDataMember lightCopy(HashMap<Integer,CustomDataMember> visited){
		CustomDataMember result = null;
		int start = getLatestCopyVersion();
		boolean flag =true;
		while(flag){
			//String name, String group, int valueType,
			//int makeMethod, boolean isInner, int classID,boolean isCopy
			start++;
			String name = this.name+"("+start+")";
			result = new CustomDataMember(name,this.group,this.valueType,this.makeMethod,this.isInner,this.classID,true);
			
			if(!result.saveEmptyMemberDM())
				flag = true;
			else
				flag = false;
		}
		
		int copyDMID = result.getID();
		setFunctionalByDMId(getFunctionalByDMId(this.getID()), copyDMID);
		setArityByDMId(getArityByDMId(this.getID()), copyDMID);
		
		int id = this.getID();
		visited.put(id,result);
		ArrayList<Base> bases = getBasesByDMId(id) ;
		
		ArrayList<Base> newBases = new ArrayList<Base>();
		for(Base base:bases){
			if(base.getDMType()==DataMember.CUSTOM_DATAMEMBER){
				//int dmtype, int id, boolean inverse
			    if(visited.containsKey(base.getID())) {
					Base mbase = new Base(DataMember.CUSTOM_DATAMEMBER,
							visited.get(base.getID()).getID(), false);
                    newBases.add(mbase);
				}else{
					if(!isCopy(base.getID())){
						CustomDataMember cdm = CustomDataMember.getCustomDataMemberById(base.getID());
						CustomDataMember copyDM  = cdm.lightCopy(visited);
						Base mbase = new Base(DataMember.CUSTOM_DATAMEMBER,
								copyDM.getID(), false);
	                    newBases.add(mbase);
					}else{
						newBases.add(base) ;
					}
				}
			}else{
				newBases.add(base) ;
			}
		}
		
		saveMemberOfDM(copyDMID, newBases) ;
		
		return result;
	}
	
	/**
	 * deep copy the datamember and return the top datamember
	 * if the datamember is made from copy, we do not copy again
	 * @return
	 */
	public CustomDataMember deepCopy(){
		CustomDataMember result = null;
		
		HashMap<Integer,CustomDataMember> visited= new HashMap<Integer,CustomDataMember>();
		result = this.lightCopy(visited) ;
		
		return result;
	}
	
	/**
	 * 将当前datamember复制得到其一个拷贝，作为当前group下制作的一个datamember
	 * @return
	 */
	public CustomDataMember saveAsCopy(){
		CustomDataMember result = null;
		int start = getLatestCopyVersion();
		boolean flag =true;
		while(flag){
			//String name, String group, int valueType,
			//int makeMethod, boolean isInner, int classID,boolean isCopy
			start++;
			String name = this.name+"("+start+")";
			result = new CustomDataMember(name,this.group,this.valueType,this.makeMethod,this.isInner,this.classID,false);
			if(!result.saveEmptyMemberDM())
				flag = true;
			else
				flag = false;
		}
		
		int copyDMID = result.getID();
		setFunctionalByDMId(getFunctionalByDMId(this.getID()), copyDMID);
		setArityByDMId(getArityByDMId(this.getID()), copyDMID);
		
		int id = this.getID();
		ArrayList<Base> bases = getBasesByDMId(id) ;
		ArrayList<Base> newBases = new ArrayList<Base>();
		for(Base base:bases){
			if(base.getDMType()==DataMember.CUSTOM_DATAMEMBER){
				//int dmtype, int id, boolean inverse
				if (base.getID() == id) {
					Base mbase = new Base(DataMember.CUSTOM_DATAMEMBER,
							copyDMID, false);
					newBases.add(mbase);
				}else
					newBases.add(base) ;
			}else{
				newBases.add(base) ;
			}
		}
		
		saveMemberOfDM(copyDMID, newBases) ;
		
		return result;
	}
	
	/**
	 * get this datamember's latest copy version,start from 1
	 * @return -1 if this datamember has not been serialized
	 */
	private int getLatestCopyVersion(){
		int result = 0;
		int groupId = Group.getGroupIdByName(this.group);
		if (groupId < 0)
			return result;
		int dmId = getDMIdByNameGroupClassIDIsCopy(this.name, this.group,this.isInner,this.classID,this.isCopy);
		if (dmId <= 0)
			return result;
		try {
			Connection conn = DBConnectionFactory.getConnection();
			PreparedStatement stmt = conn
					.prepareStatement("select count(*) as count from data_member where group_id=? and isInner=? and class_id=? and isCopy=1 and name like ?");
			stmt.setInt(1, groupId);
			stmt.setBoolean(2, this.isInner);
			stmt.setInt(3, this.classID);
			String name = this.name+"(%)";
			stmt.setString(4,name);
			ResultSet rs = stmt.executeQuery();
			if(rs.next()){
				result = rs.getInt("count");
			}
			rs.close();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}

		return result;
	}
	
	public static int getLatestCopyVersion(String name,String group,boolean isInner,int classID,boolean isCopy){
		int result = 0;
		int groupId = Group.getGroupIdByName(group);
		if (groupId < 0)
			return result;
		int dmId = getDMIdByNameGroupClassIDIsCopy(name, group,isInner,classID,isCopy);
		if (dmId <= 0)
			return result;
		try {
			Connection conn = DBConnectionFactory.getConnection();
			PreparedStatement stmt = conn
					.prepareStatement("select count(*) as count from data_member where group_id=? and isInner=? and class_id=? and isCopy=1 and name like ?");
			stmt.setInt(1, groupId);
			stmt.setBoolean(2, isInner);
			stmt.setInt(3, classID);
			String mname = name+"(%)";
			stmt.setString(4,mname);
			ResultSet rs = stmt.executeQuery();
			if(rs.next()){
				result = rs.getInt("count");
			}
			rs.close();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}

		return result;
	}
	
	/**
	 * 删除datamember，从dm_from , view_dm中查看是否有依赖于该datamember的其它datamber或者view
	 * 如果存在，那么就要进行深拷贝。然后在dm_from,view_dm表中将引用这个datamember的对应记录进行更新
	 * 最后从datamember,dm_from,view_dm中删除这个datamember
	 * @param id . the datamember id which must be custom datamember id 
	 */
	public static void delete(int id){
		HashSet<Integer> dmIds = new HashSet<Integer>();
		HashSet<Integer> viewIds = new HashSet<Integer>();
		try {
			Connection conn = DBConnectionFactory.getConnection();
			Statement stmt = conn.createStatement();
			ResultSet rs = stmt.executeQuery(String.format(
					"select dm_id from dm_from "
							+ "where from_type = %d and from_id = %d",
					DataMember.CUSTOM_DATAMEMBER, id));
			while (rs.next()) {
				dmIds.add(rs.getInt("dm_id"));
			}
			rs.close();
			rs = null;
			
			rs = stmt.executeQuery(String.format(
					"select view_id from view_dm "
					+ "where dm_type = %d and dm_id = %d",
			DataMember.CUSTOM_DATAMEMBER, id));
			while(rs.next()){
				viewIds.add(rs.getInt("view_id"));
			}
			rs.close();
			rs = null;
			
			boolean flag = dmIds.size()+viewIds.size()>0?true:false;
			if(flag){
				CustomDataMember thisDM = CustomDataMember.getCustomDataMemberById(id);
				CustomDataMember copyDM = thisDM.deepCopy();
				int copyID = copyDM.getID();
				PreparedStatement dmStmt= conn.prepareStatement("update dm_from set from_id=?  where dm_id=? and from_type=? and from_id=?");
				PreparedStatement viewStmt = conn.prepareStatement("update view_dm set dm_id=? where view_id=? and dm_type=? and dm_id=?");
				for(Integer dmID:dmIds){
					dmStmt.setInt(1, copyID);
					dmStmt.setInt(2, dmID);
					dmStmt.setInt(3, CUSTOM_DATAMEMBER);
					dmStmt.setInt(4, id);
					dmStmt.executeUpdate();
 				}
				
				for(Integer viewID:viewIds){
					viewStmt.setInt(1, copyID);
					viewStmt.setInt(2, viewID);
					viewStmt.setInt(3, CUSTOM_DATAMEMBER);
					viewStmt.setInt(4, id);
					viewStmt.executeUpdate();
				}
				
				dmStmt.close();
				viewStmt.close();
			}
			
			stmt.execute(String.format(
					"delete from view_dm where dm_type=%d and  dm_id=%d",
					DataMember.CUSTOM_DATAMEMBER, id));
			stmt.execute(String.format("delete from dm_from "
					+ "where dm_id = %d", id));
			stmt.execute(String.format("delete from data_member "
					+ "where id = %d", id));
			
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}

		for (Integer dmId : dmIds) {
			kill(dmId);
		}
	}
	
	/*删除以rowID标识的customdatamember对应的规则
	 * 如果是chain方式生成的中间规则，那么将它对应的datamember删除。
	 * */
	public static void deleteRuleByRowID(int rowID){
		try {
			Connection conn = DBConnectionFactory.getConnection();
			Statement stmt = conn.createStatement();
			boolean isChainRule = false;
			ResultSet rs = stmt.executeQuery("select dm_id from dm_from where id="+rowID);
			int dm_id = -1;
			if(rs.next()){
				dm_id= rs.getInt("dm_id");
				if(CustomDataMember.getMakeMethodByDMId(dm_id)==DataMember.MAKE_METHOD_CHAIN){
					isChainRule = true;
				}
			}
			rs.close();
			stmt.executeUpdate("delete from dm_from where id="+rowID);
			if(isChainRule&&dm_id>0){
				stmt.executeUpdate("delete from data_member where id="+dm_id);
			}
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}		
	}
	
	/**
	 * 彻底删除datamember (自定义或者系统生成的拷贝)
	 * 需要依次： 1.从表dm_from中递归彻底删除依赖于该datamember的其它datamember
	 * 2.从表dm_from中彻底删除该datamember的记录 3.从表view_dm中彻底删除有关该datamember的记录
	 * 4.从表data_member中将该data_member彻底删除
	 * 
	 * @param id
	 *            . the datamember id
	 */
	private static void kill(int id) {
		HashSet<Integer> dmIds = new HashSet<Integer>();
		try {
			Connection conn = DBConnectionFactory.getConnection();
			Statement stmt = conn.createStatement();
			ResultSet rs = stmt.executeQuery(String.format(
					"select dm_id from dm_from "
							+ "where from_type = %d and from_id = %d",
					DataMember.CUSTOM_DATAMEMBER, id));
			while (rs.next()) {
				dmIds.add(rs.getInt("dm_id"));
			}
			rs.close();

			stmt.execute(String.format(
					"delete from view_dm where dm_type=%d and  dm_id=%d",
					DataMember.CUSTOM_DATAMEMBER, id));

			stmt.execute(String.format("delete from dm_from "
					+ "where dm_id = %d", id));
			stmt.execute(String.format("delete from data_member "
					+ "where id = %d", id));
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}

		for (Integer dmId : dmIds) {
			kill(dmId);
		}
	}	

	/**
	 * get the custom datamember
	 * 
	 * @param dmId
	 * @return
	 */
	public static CustomDataMember getCustomDataMemberById(int dmId) {
		CustomDataMember result = null;
		try {
			Connection conn = DBConnectionFactory.getConnection();
			Statement stmt = conn.createStatement();
			ResultSet rs = stmt
					.executeQuery(String
							.format("select name,group_id,value_type,functional,make_method,isInner,class_id,arity,isCopy from data_member "
									+ "where id=%d", dmId));
			String name = null;
			String groupName = null;
			int value_type = 0;
			int make_method = 0;
			int classId = 0;
			int arity = 2;
			boolean functional = false;
			boolean isInner = false;
			boolean isCopy = false;
			if (rs.next()) {
				name = rs.getString("name");
				groupName = Group.getGroupNameById(rs.getInt("group_id"));
				value_type = rs.getInt("value_type");
				make_method = rs.getInt("make_method");
				classId = rs.getInt("class_id");
				arity = rs.getInt("arity");
				functional = rs.getBoolean("functional");
				isInner = rs.getBoolean("isInner");
				isCopy = rs.getBoolean("isCopy");
				result = new CustomDataMember(name, groupName, value_type,
						make_method, isInner, classId,isCopy);
				result.setArity(arity);
				result.setFunctional(functional);
			}
			rs.close();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return result;
	}
    
	/**
	 * GET dmid by name group class
	 * @param name.the dm name
	 * @param group. group name 
	 * @param isInner.whether the class is inner clas
	 * @param classID. class id
	 * @param isCpoy. 
	 * @return -1 if not exist
	 */
	public static  int getDMIdByNameGroupClassIDIsCopy(String name, String group,boolean isInner, int classID,boolean isCopy) {
		int dmId = -1;
		int groupID = Group.getGroupIdByName(group);
		if (groupID <= 0)
			return dmId;
		dmId = getDMIdByNameGroupClassIDIsCopy(name,groupID,isInner,classID,isCopy);
		return dmId;
	}

	/**
	 * GET dmid by name group class
	 * @param name.the dm name
	 * @param groupID. the group id
	 * @param isInner.whether the class is inner clas
	 * @param classID. class id
	 * @param isCopy
	 * @return -1 if not exist
	 */
	public static int getDMIdByNameGroupClassIDIsCopy(String name, int groupID,boolean isInner,int classID,boolean isCopy) {
		int dmId = -1;
		try {
			Connection conn = DBConnectionFactory.getConnection();
			PreparedStatement stmt = conn.prepareStatement("select id from data_member where name =? and group_id =? and isInner=? and class_id=? and isCopy=?");
			stmt.setString(1, name);
			stmt.setInt(2, groupID);
			stmt.setBoolean(3, isInner);
			stmt.setInt(4, classID);
			stmt.setBoolean(5, isCopy);
			ResultSet rs = stmt.executeQuery();
			if (rs.next()) {
				dmId = rs.getInt("id");
			}
			rs.close();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return dmId;
	}

	public int getClassID() {
		return this.classID;
	}
	
	public static int getClassIDByDMID(int cdmID){
		int result = -1;
		try {
			Connection conn = DBConnectionFactory.getConnection();
			Statement stmt = conn.createStatement();
			ResultSet rs = stmt
					.executeQuery(String.format(
							"select class_id from data_member "
									+ "where id=%d", cdmID));
			if (rs.next()) {
				result = rs.getInt("class_id");
			}
			rs.close();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return result;
	}
	
	public static int getGroupIDByDMID(int cdmID){
		int result = -1;
		try {
			Connection conn = DBConnectionFactory.getConnection();
			Statement stmt = conn.createStatement();
			ResultSet rs = stmt
					.executeQuery(String.format(
							"select group_id from data_member "
									+ "where id=%d", cdmID));
			if (rs.next()) {
				result = rs.getInt("group_id");
			}
			rs.close();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return result;
	}
	
	public boolean isInner(){
		return this.isInner;
	}

	public static boolean isInner(int cdm_id) {
		boolean result = false;
		try {
			Connection conn = DBConnectionFactory.getConnection();
			Statement stmt = conn.createStatement();
			ResultSet rs = stmt
					.executeQuery(String.format(
							"select isInner from data_member "
									+ "where id=%d", cdm_id));
			if (rs.next()) {
				result = rs.getBoolean("isInner");
			}
			rs.close();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return result;
	}
	
	public static boolean isCopy(int cdm_id){
		boolean result = false;
		try {
			Connection conn = DBConnectionFactory.getConnection();
			Statement stmt = conn.createStatement();
			ResultSet rs = stmt
					.executeQuery(String.format(
							"select isCopy from data_member "
									+ "where id=%d", cdm_id));
			if (rs.next()) {
				result = rs.getBoolean("isCopy");
			}
			rs.close();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return result;
	}
	
	public boolean isCopy(){
		return this.isCopy;
	}
	
	/**
	 * 判断以dmid标识的 custom datamember 是否存在
	 * @param dmid
	 * @return
	 */
	public static boolean isThere(int dmid){
		boolean result = false;
		try {
			Connection conn = DBConnectionFactory.getConnection();
			Statement stmt = conn.createStatement();
			ResultSet rs = stmt
					.executeQuery(String.format(
							"select null from data_member "
									+ "where id=%d", dmid));
			if (rs.next()) {
				result = true;
			}
			rs.close();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * get the datamember or uri on which this datamember based
	 * 
	 * @param dmID
	 *            . The datamember ID
	 * @return
	 */
	public static ArrayList<Base> getBasesByDMId(int dmID) {
		ArrayList<Base> result = new ArrayList<Base>();
		try {
			Connection conn = DBConnectionFactory.getConnection();
			Statement stmt = conn.createStatement();
			ResultSet rs = stmt.executeQuery(String.format(
					"select id,from_type, from_id,inverse " + "from dm_from "
							+ "where dm_id = %d order by seq", dmID));
			while (rs.next()) {
				int rowID = rs.getInt("id");
				int fromType = rs.getInt("from_type");
				int fromId = rs.getInt("from_id");
				boolean inverse = rs.getBoolean("inverse");
				Base base = new Base(fromType, fromId, inverse);
				base.setRowID(rowID);
				result.add(base);
			}
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return result;
	}



	/**
	 * get the value type of the datamember (link,attribute)
	 * 
	 * @param DMId
	 *            . the data member id
	 * @return
	 */
	public static int getValueTypeByDMId(int DMId) {
		int valueType = -1;
		try {
			Connection conn = DBConnectionFactory.getConnection();
			Statement stmt = conn.createStatement();
			ResultSet rs = stmt
					.executeQuery(String.format(
							"select valueType from data_member "
									+ "where id=%d", DMId));
			if (rs.next()) {
				valueType = rs.getInt("value_type");
			}
			rs.close();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return valueType;
	}

	public int getMakeMethod() {
		if (this.makeMethod < 0) {
			try {
				this.makeMethod = getMakeMethodByDMId(getDMIdByNameGroupClassIDIsCopy(
						this.name, this.group,this.isInner,this.classID,this.isCopy));
			} catch (Throwable e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return this.makeMethod;
	}

	/**
	 * get the make method of the data member
	 * 
	 * @param DMId
	 *            . the data member id
	 * @return
	 */
	public static int getMakeMethodByDMId(int DMId) {
		int makeMethod = -1;
		try {
			Connection conn = DBConnectionFactory.getConnection();
			Statement stmt = conn.createStatement();
			ResultSet rs = stmt.executeQuery(String.format(
					"select make_method from data_member " + "where id=%d",
					DMId));
			if (rs.next()) {
				makeMethod = rs.getInt("make_method");
			}
			rs.close();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return makeMethod;
	}

	public String getName() {
		return name;
	}

	public int getID() {
		if (this.id <= 0)
			this.id = getDMIdByNameGroupClassIDIsCopy(this.name, this.group,this.isInner,this.classID,this.isCopy);
		return this.id;
	}

	public void setID(int id) {
		this.id = id;
	}

	/**
	 * set the arity of datamember which can be used for rules generation
	 * 
	 * @param dmID
	 * @param arity
	 *            .defult value 2. If datamember is made from
	 *            make_method_connect,return value is more than 2.
	 */
	public static void setArityByDMId(int dmID, int arity) {
		try {
			Connection conn = DBConnectionFactory.getConnection();
			PreparedStatement stmt = conn
					.prepareStatement("update data_member set arity=? where id=?");
			stmt.setInt(1, arity);
			stmt.setInt(2, dmID);
			stmt.executeUpdate();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	public void setValueType(int valueType) {
		this.valueType = valueType;
	}	

	public int getArity() {
		return this.arity;
	}

	public void setArity(int arity) {
		this.arity = arity;
	}

	/**
	 * get the arity of custom datamember
	 * 
	 * @param dmID
	 *            return defult value 2. If datamember is made from
	 *            make_method_connect,return value is more than 2.
	 */
	public static int getArityByDMId(int dmID) {
		int result = 2;
		try {
			Connection conn = DBConnectionFactory.getConnection();
			PreparedStatement stmt = conn
					.prepareStatement("select arity from data_member where id =?");
			stmt.setInt(1, dmID);
			ResultSet rs = stmt.executeQuery();
			if (rs.next()) {
				result = rs.getInt("arity");
			}
			rs.close();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return result;
	}

	public String getGroup() {
		return group;
	}

	/**
	 * check the data member whether functional
	 * 
	 * @param DMId
	 *            . the data member id
	 * @return
	 */
	public static boolean getFunctionalByDMId(int DMId) {
		boolean functional = false;
		try {
			Connection conn = DBConnectionFactory.getConnection();
			Statement stmt = conn.createStatement();
			ResultSet rs = stmt.executeQuery(String.format(
					"select functional from data_member " + "where id= %d",
					DMId));
			if (rs.next()) {
				functional = rs.getBoolean("functional");
			}
			rs.close();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return functional;
	}

	/**
	 * set the value type of the datamember
	 * 
	 * @param valueType
	 */
	public static void setValueType(int valueType, int DMId) {
		try {
			Connection conn = DBConnectionFactory.getConnection();
			PreparedStatement stmt = conn
					.prepareStatement("update data_member set value_type=? where id=?");
			stmt.setInt(1, valueType);
			stmt.setInt(2, DMId);
			stmt.executeUpdate();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	public int getValueType() {
		if (this.valueType < 0) {
			this.valueType = getValueTypeByDMId(this.getID());
		}
		return this.valueType;
	}

	public boolean getFunctional() {
		return this.functional;
	}

	public void setFunctional(boolean functional) {
		this.functional = functional;
	}

	/**
	 * set functional of the datamember
	 * 
	 * @param valueType
	 */
	public static void setFunctionalByDMId(boolean functional, int DMId) {
		try {
			Connection conn = DBConnectionFactory.getConnection();
			PreparedStatement stmt = conn
					.prepareStatement("update data_member set functional=? where id=?");
			stmt.setBoolean(1, functional);
			stmt.setInt(2, DMId);
			stmt.executeUpdate();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 得到以dmid标志的 custom datamember作为成员的view的列表
	 * 
	 * @param dmid
	 *            . datamember id
	 * @return. empty if none
	 */
	public static HashSet<Integer> getViewHasDataMember(Integer dmid) {
		HashSet<Integer> result = new HashSet<Integer>();
		Connection con = DBConnectionFactory.getConnection();
		try {
			Statement stmt = con.createStatement();
			ResultSet rs = stmt
					.executeQuery(String
							.format("select distinct view_id from view_dm where dm_type=%d and dm_id=%d",
									DataMember.CUSTOM_DATAMEMBER, dmid));
			while (rs.next()) {
				int viewId = rs.getInt("view_id");
				result.add(new Integer(viewId));
			}
			rs.close();
			stmt.close();
			con.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return result;
	}

	/**
	 * check whether the datamember is functional
	 * 
	 * @param DMId
	 * @return
	 */
	public static boolean isFunctional(int DMId) {
		boolean result = false;
		try {
			Connection conn = DBConnectionFactory.getConnection();
			PreparedStatement stmt = conn
					.prepareStatement("select functional from data_member where id=?");
			stmt.setInt(1, DMId);
			ResultSet rs = stmt.executeQuery();
			if (rs.next()) {
				result = rs.getBoolean("functional");
			}
			rs.close();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * serialize the datamember. if the datamember has existed ,return false
	 */
	public boolean serialize() {
		int groupId = Group.getGroupIdByName(this.group);
		if (groupId < 0)
			return false;
		int dmId = getDMIdByNameGroupClassIDIsCopy(this.name, this.group,this.isInner,this.classID,this.isCopy);
		if (dmId >= 0)
			return false;
		if(this.bases==null){
			throw new IllegalArgumentException("The bases of the datamember cannot be null");
		}
		try {
			Connection conn = DBConnectionFactory.getConnection();
			PreparedStatement stmt = conn
					.prepareStatement("insert into data_member(name,group_id,value_type,make_method,class_id,isInner,isCopy,create_time,update_time) "
							+ "values(?,?,?,?,?,?,?,NOW(),NOW())");
			stmt.setString(1, this.name);
			stmt.setInt(2, groupId);
			stmt.setInt(3, this.valueType);
			stmt.setInt(4, this.makeMethod);
			stmt.setInt(5, this.classID);
			stmt.setBoolean(6, this.isInner);
			stmt.setBoolean(7, this.isCopy) ;
			stmt.executeUpdate();
			stmt.close();
			dmId = getDMIdByNameGroupClassIDIsCopy(this.name, this.group,this.isInner,this.classID,this.isCopy);
			PreparedStatement pstmt = conn
					.prepareStatement("insert into dm_from(dm_id, from_type, from_id,seq,inverse) "
							+ "values(?, ?, ?,?,?)");
			pstmt.setInt(1, dmId);
			for (int i = 0; i < this.bases.size(); i++) {
				int fromType = this.bases.get(i).getDMType();
				int fromId = this.bases.get(i).getID();
				boolean inverse = this.bases.get(i).isInverse();
				pstmt.setInt(2, fromType);
				pstmt.setInt(3, fromId);
				pstmt.setInt(4, i);
				pstmt.setBoolean(5, inverse);
				pstmt.executeUpdate();
			}
			pstmt.close();
			conn.close();
			return true;
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return false;
	}
	
	/**
	 * save datamember bases. If bases already exist,overwrite it.
	 * @param dmId. datamember id
	 * @param bases. bases
	 */
	private static void saveMemberOfDM(int dmId,ArrayList<Base> bases){
		try {
			Connection conn = DBConnectionFactory.getConnection();
			Statement stmt = conn.createStatement();
			stmt.executeUpdate(String.format(
					"delete from dm_from " +
					"where dm_id = %d", dmId));
			stmt.close();
			PreparedStatement pstmt = conn
					.prepareStatement("insert into dm_from(dm_id, from_type, from_id,seq,inverse) "
							+ "values(?, ?, ?,?,?)");
			pstmt.setInt(1, dmId);
			for (int i = 0; i < bases.size(); i++) {
				int fromType = bases.get(i).getDMType();
				int fromId = bases.get(i).getID();
				boolean inverse = bases.get(i).isInverse();
				pstmt.setInt(2, fromType);
				pstmt.setInt(3, fromId);
				pstmt.setInt(4, i);
				pstmt.setBoolean(5, inverse);
				pstmt.executeUpdate();
			}
			pstmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * append datamember bases. 
	 * @param dmId. datamember id
	 * @param bases. bases
	 */
	public static void appendMemberOfDM(int dmId,ArrayList<Base> originbases){
		int groupID = CustomDataMember.getGroupIDByDMID(dmId);
		try {
			if(CustomDataMember.getMakeMethodByDMId(dmId)!=DataMember.MAKE_METHOD_MERGE){
				throw new IllegalArgumentException("The datamember make method must be merge");
			}
			Connection conn = DBConnectionFactory.getConnection();
			ArrayList<Base> oldbases = CustomDataMember.getBasesByDMId(dmId);
			HashSet<Base> visited = new HashSet<Base>();
			ArrayList<Base> bases = new ArrayList<Base>();
			for(Base base:oldbases){
				if(!visited.contains(base)){
					visited.add(base);
					bases.add(base);
				}
			}
			for (Base base : originbases) {
				if (!visited.contains(base)) {
					visited.add(base);
					int type = base.getDMType();
					int id = base.getID();
					boolean inverse = base.isInverse();
					if (type == DataMember.URI_DATAMEMBER) {
						bases.add(base);
					} else {
						boolean hasAuthor = CustomDataMember.hasAuthor(groupID,
								id);
						if (hasAuthor) {
							bases.add(base);
						} else {
							CustomDataMember cdm = CustomDataMember
									.getCustomDataMemberById(id).deepCopy();
							int copyID = cdm.getID();
							CustomDataMember.setTMP(copyID, false);
							Base newbase = new Base(type, copyID, inverse);
							bases.add(newbase);
						}
					}
				}
			}		
			Statement stmt = conn.createStatement();
			stmt.executeUpdate(String.format(
					"delete from dm_from " +
					"where dm_id = %d", dmId));
			stmt.close();
			PreparedStatement pstmt = conn
					.prepareStatement("insert into dm_from(dm_id, from_type, from_id,seq,inverse) "
							+ "values(?, ?, ?,?,?)");
			pstmt.setInt(1, dmId);
			for (int i = 0; i < bases.size(); i++) {
				int fromType = bases.get(i).getDMType();
				int fromId = bases.get(i).getID();
				boolean inverse = bases.get(i).isInverse();
				pstmt.setInt(2, fromType);
				pstmt.setInt(3, fromId);
				pstmt.setInt(4, i);
				pstmt.setBoolean(5, inverse);
				pstmt.executeUpdate();
			}
			pstmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * just save the datamember without dm_froms. if the datamember has existed ,return false
	 */
	private boolean saveEmptyMemberDM(){
		int groupId = Group.getGroupIdByName(this.group);
		if (groupId < 0)
			return false;
		int dmId = getDMIdByNameGroupClassIDIsCopy(this.name, this.group,this.isInner,this.classID,this.isCopy);
		if (dmId >= 0)
			return false;
		try {
			Connection conn = DBConnectionFactory.getConnection();
			PreparedStatement stmt = conn
					.prepareStatement("insert into data_member(name,group_id,value_type,make_method,class_id,isInner,isCopy,create_time,update_time) "
							+ "values(?,?,?,?,?,?,?,NOW(),NOW())");
			stmt.setString(1, this.name);
			stmt.setInt(2, groupId);
			stmt.setInt(3, this.valueType);
			stmt.setInt(4, this.makeMethod);
			stmt.setInt(5, this.classID);
			stmt.setBoolean(6, this.isInner);
			stmt.setBoolean(7, this.isCopy) ;
			stmt.executeUpdate();
			stmt.close();
			conn.close();
			return true;
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return false;
	}

	/**
	 * rename the datamember
	 * 
	 * @param DMID
	 * @param newName
	 * @param groupID
	 * @param isInner
	 * @param classID
	 * @return if success return true. If names have conflict or operation
	 *         failure, return false;
	 */
	public static boolean rename(int DMID, String newName, int groupID,boolean isInner,int classID,boolean isCopy) {
		int checkId = getDMIdByNameGroupClassIDIsCopy(newName, groupID,isInner,classID,isCopy);
		if (checkId >= 0 && checkId != DMID)
			return false;
		if (checkId == DMID)
			return true;
		try {
			Connection conn = DBConnectionFactory.getConnection();
			PreparedStatement stmt = conn
					.prepareStatement("update data_member set name=?, update_time=NOW() where id=?");
			stmt.setString(1, newName);
			stmt.setInt(2, DMID);
			stmt.executeUpdate();
			stmt.close();
			conn.close();
			return true;
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return false;
	}
	
	public static void setTMP(int dmid,boolean tmp){
		try {
			Connection conn = DBConnectionFactory.getConnection();
			Statement stmt = conn.createStatement();
			stmt.executeUpdate(String.format("update data_member set tmp=%b where id=%d",tmp,dmid));
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	public static void clearTMPDM(){
		try {
			Connection conn = DBConnectionFactory.getConnection();
			Statement stmt = conn.createStatement();
			ResultSet rs = stmt.executeQuery("select id,create_time from data_member where tmp=1");
			while(rs.next()){
				int id =rs.getInt("id");
				Date date =rs.getTimestamp("create_time");
		    	Date now = new Date();
		    	Calendar c1 =Calendar.getInstance();
		    	Calendar c2 = Calendar.getInstance();
		    	c1.setTime(date) ;
		    	c2.setTime(now) ;
		    	long difference = now.getTime()-date.getTime();
	    		/*为了防止正在编辑的dm正好遇上clear任务*/
	    		if(difference>0.5*60*60*1000){
	    			CustomDataMember.delete(id);
	    		}
			}
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + classID;
		result = prime * result + ((group == null) ? 0 : group.hashCode());
		result = prime * result + (isCopy ? 1231 : 1237);
		result = prime * result + (isInner ? 1231 : 1237);
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		CustomDataMember other = (CustomDataMember) obj;
		if (classID != other.classID)
			return false;
		if (group == null) {
			if (other.group != null)
				return false;
		} else if (!group.equals(other.group))
			return false;
		if (isCopy != other.isCopy)
			return false;
		if (isInner != other.isInner)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}



	public static class Base {
		private int dmtype;
		private int id;
		private boolean inverse;
		//数据库中自定义规则对应的行
		private int rowID;

		public Base(int dmtype, int id, boolean inverse) {
			this.dmtype = dmtype;
			this.id = id;
			this.inverse = inverse;
		}
		
		public void setRowID(int rowID){
			this.rowID = rowID;
		}
		
		public int getRowID(){
			 return this.rowID;
		}
		
		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + dmtype;
			result = prime * result + id;
			return result;
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			Base other = (Base) obj;
			if (dmtype != other.dmtype)
				return false;
			if (id != other.id)
				return false;
			return true;
		}

		public int getDMType() {
			return this.dmtype;
		}

		public int getID() {
			return this.id;
		}

		public boolean isInverse() {
			return this.inverse;
		}
	}
	
   /**
    * 得到这个自定义datamember对应的底层规则
    * @return
    */
	public ArrayList<Rule> getRules(){
		ArrayList<Rule> rules = new ArrayList<Rule>();
    	int dmid = this.getID();
    	CustomDataMember dm = CustomDataMember.getCustomDataMemberById(dmid) ;
		arity = dm.getArity();
		String name = dm.getName();
		String group = dm.getGroup();
		boolean isInner = dm.isInner();
		boolean isCopy = dm.isCopy();
		int classID = dm.getClassID();
		URIResource pred_resource =  ResourceFactory.getInstance().createCustomDatamemberURIResource(group, name,isInner,classID,isCopy);
		Predicate pred = new Predicate(pred_resource,arity);
    	rules = ProductionMemory.getRules(pred);
    	return rules;
    }
}
